//@ts-nocheck
import {createStore} from 'redux';
import rootReducer from './reducers';
import compose from '../redux/compose';

//如何定一个专业的中间件 ---> 实现一个日志中间件
//格式是定死的 柯里化 三层
const logger = function (api: any) {//api 现在你理解为接受的是store即可
  return function loggerNext(next: any) {//调用下一个中间件的方法 现在你可以理解为store.dispatch
    return function loggerDispatch(action: any) {//dispatch要派发的动作
      console.log('变更前的老状态', api.getState());//store.dispatch
      next(action);//调用下一个中间件
      console.log('变更后的新状态', api.getState());
    }
    //↑以后再调用store.dispatch调用就是这个函数, applyMiddleware里会换掉原本的dispatch(return {...store, dispatch})
  }
}


//如何定一个专业的中间件 ---> 实现thunk异步中间件
//格式是定死的 柯里化 三层
const thunk = function (api: any) {//api 现在你理解为接受的是store即可
  return function thunkNext(next: any) {//调用下一个中间件的方法 现在你可以理解为store.dispatch
    return function thunkDispatch(action: any) {//dispatch要派发的动作
      if (typeof action === 'function') { //说明是一个thunk 异步任务 交给它自己处理即可
        return action(api.dispatch, api.getState);
      }
      return next(action);//调用下一个中间件
    }
    //↑以后再调用store.dispatch调用就是这个函数, applyMiddleware里会换掉原本的dispatch(return {...store, dispatch})
  }
}


//如何定一个专业的中间件 ---> 实现thunk异步中间件
//格式是定死的 柯里化 三层
const promise = function (api: any) {//api 现在你理解为接受的是store即可
  return function promiseNext(next: any) {//调用下一个中间件的方法 现在你可以理解为store.dispatch
    return function promiseDispatch(action: any) {//dispatch要派发的动作
      if (typeof action.then === 'function') { //说明是一个thunk 异步任务 交给它自己处理即可
        return action.then(newAction=>api.dispatch(newAction));
      }
      return next(action);//调用下一个中间件
    }
    //↑以后再调用store.dispatch调用就是这个函数, applyMiddleware里会换掉原本的dispatch(return {...store, dispatch})
  }
}

function applyMiddleware(/*middleware*/...middlewares){
  return function(createStore){
    return function(reducer){
      const store = createStore(reducer);

      // const dispatch = middleware(store)(store.dispatch);

      // eslint-disable-next-line prefer-const
      let dispatch; //← 会被狸猫换太子 变成改造后的dispatch方法
      const middlewareAPI = {
        getState: store.getState,
        dispatch: (action) => dispatch/*← 这里这个dispatch是下面 dispatch = middleware(middlewareAPI)(store.dispatch) 赋的值*/(action)
      }

      //dispatch = middleware(middlewareAPI)(store.dispatch);

      const chain = middlewares.map(middleware => middleware(middlewareAPI));

      // const [promise, thunk, logger] = chain;
      // dispatch = promise(thunk(logger(store.dispatch)))
      // ↕ 等价
      /*这里 最终这个dispatch 就是promiseDispatch→*/dispatch = compose(...chain)(store.dispatch);

      return {
        ...store,
        dispatch
      }
    }
  }
}

//const store = createStore(rootReducer);
const store = applyMiddleware(promise/*里的next是thunk*/,thunk/*里的next是logger*/,logger/*里的next是原生的dispatch*/)(createStore)(rootReducer); //你如果不想传递多个中间件, 就只能自己写一个包含所有中间的大中间件
//↑ 包装的时候是从右到左包装， 派发执行的时候 是从左向右 执行

//logger不能放在左边, 因为promise和thunk这种异步的 会再得到结果后 再次派发, 这样就可能会导致无用的打印

export default store;
